package org.spiderflow.core.expression;

import org.apache.commons.lang3.StringUtils;
import org.spiderflow.core.expression.reflection.JavaReflection;
import org.spiderflow.common.executor.ExpressionEngine;
import org.spiderflow.common.executor.FunctionExecutor;
import org.spiderflow.common.executor.FunctionExtension;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.List;
import java.util.Map;

/**
 * @author zsh
 */
@Component
public class DefaultExpressionEngine implements ExpressionEngine {

    private final List<FunctionExecutor> functionExecutors;

    private final List<FunctionExtension> functionExtensions;

    public DefaultExpressionEngine(List<FunctionExecutor> functionExecutors, List<FunctionExtension> functionExtensions) {
        this.functionExecutors = functionExecutors;
        this.functionExtensions = functionExtensions;
    }

    @PostConstruct
    private void init() {
        for (FunctionExtension extension : functionExtensions) {
            JavaReflection.getInstance().registerExtensionClass(extension.support(), extension.getClass());
        }
    }

    @Override
    public Object execute(String expression, Map<String, Object> variables) {
        if (StringUtils.isBlank(expression)) {
            return expression;
        }
        ExpressionTemplateContext context = new ExpressionTemplateContext(variables);
        for (FunctionExecutor executor : functionExecutors) {
            context.set(executor.getFunctionPrefix(), executor);
        }
        ExpressionGlobalVariables.getVariables().forEach((key, value) ->
                context.set(key, ExpressionTemplate.create(value).render(context)));
        try {
            ExpressionTemplateContext.set(context);
            return ExpressionTemplate.create(expression).render(context);
        } finally {
            ExpressionTemplateContext.remove();
        }
    }

}
